﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LGE;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Audio;

namespace Stealth
{
    public class Character : GameObject
    {
        // Atributos
        float moveSpeed = 5;
        public float jumpHeight = 12;
        public bool isStealth = false;
        public InteractiveObject interactiveObject = null;

        // Aux
        bool prevOnGround = false;
        bool isAnimating = false;
        public SpriteSheetState state;
        Texture2D interactiveObjectIndicator;

        // Audio
        bool isLeftStep = false;
        double stepTimer = 0;

        public Character(PlayScreen ps)
            : base(ps, null)
        {
            interactiveObjectIndicator = Engine.Load<Texture2D>("Images\\tile");
            state = new SpriteSheetState(this);
            state.Add(Engine.Load<Texture2D>("Images\\Character\\Vampire\\idle"), new SpriteSheet(this, 150, 150, 80, true));
            state.Add(Engine.Load<Texture2D>("Images\\Character\\Vampire\\walk"), new SpriteSheet(this, 150, 150, 80, true));
            state.Add(Engine.Load<Texture2D>("Images\\Character\\Vampire\\jump"), new SpriteSheet(this, 150, 150, 40, false));
            state.Add(Engine.Load<Texture2D>("Images\\Character\\Vampire\\fall"), new SpriteSheet(this, 150, 150, 80, false));
            state.Add(Engine.Load<Texture2D>("Images\\Character\\Vampire\\death"), new SpriteSheet(this, 150, 150, 40, false));
            state.Add(Engine.Load<Texture2D>("Images\\Character\\Vampire\\upstairs1"), new SpriteSheet(this, 120, 150, 40, false)); // UpStairs1
            state.Add(Engine.Load<Texture2D>("Images\\Character\\Vampire\\upstairs1"), new SpriteSheet(this, 120, 150, 40, false)); // UpStairs2
            state.Add(Engine.Load<Texture2D>("Images\\Character\\Vampire\\upstairs1"), new SpriteSheet(this, 120, 150, 40, false)); // DownStairs1
            state.Add(Engine.Load<Texture2D>("Images\\Character\\Vampire\\upstairs1"), new SpriteSheet(this, 120, 150, 40, false)); // DownStairs2
            state.Add(Engine.Load<Texture2D>("Images\\Character\\Vampire\\upstairs1"), new SpriteSheet(this, 120, 150, 20, false)); // DoorIn
            state.Add(Engine.Load<Texture2D>("Images\\Character\\Vampire\\upstairs1"), new SpriteSheet(this, 120, 150, 20, false)); // doorOut
            state.Change(States.Walk);
            state.Change(States.Idle);
            position = new Vector2(200, 700);//1000, 765);//500, 1300);
            drawPosition = new Vector2(1280 / 2, 720 / 2);
            HitBox = new Rectangle(0, 0, 80, 150);
            origin = new Vector2(150 / 2, 150 / 2);
        }

        public override void Update(GameTime gameTime)
        {
            state.Update(gameTime);
            if (isAnimating) { ExecuteAnimation(); return; }
            speed.X = 0;
            UpdateInput(gameTime);
            //UpdateWalkSound(gameTime);
            prevOnGround = onGround;
            CheckCollisionWithMap(gameTime);
            if (onGround && !prevOnGround) Audio.PlayCue("vampire_fall");
            UpdateNearestInteractive();
        }

        public void UpdateWalkSound(GameTime gameTime)
        {
            if (speed.X != 0 && onGround)
            {
                stepTimer += gameTime.ElapsedGameTime.TotalMilliseconds;
                if (stepTimer >= 600)
                {
                    stepTimer = 0;
                    if (isLeftStep)
                        Audio.PlayCue("vampire_step1");
                    else
                        Audio.PlayCue("vampire_step2");
                    isLeftStep = !isLeftStep;
                }
            }
        }

        public void UpdateNearestInteractive()
        {
            if (interactiveObject != null) interactiveObject.isGlowing = false;
            interactiveObject = null;
            foreach (var iObj in ps.AllInteratives)
            {
                if (Collision(iObj))
                {
                    interactiveObject = iObj;
                    interactiveObject.isGlowing = true;
                    return;
                }
            }
        }

        private void ExecuteAnimation()
        {
            switch (state.actualState)
            {
                case States.DoorIn:
                    isStealth = true;
                    interactiveObject.isOccupied = true;
                    if (state.completed && Input.KeyPressed(Keys.C))
                    {
                        Audio.PlayCue("door");
                        state.Change(States.DoorOut);
                    }
                    break;
                case States.DoorOut:
                    if (state.completed)
                    {
                        interactiveObject.isOccupied = false;
                        isStealth = false;
                        state.Change(States.Idle);
                        isAnimating = false;
                    }
                    break;
                case States.UpStairs1:
                    if (state.completed)
                    {
                        Vector2 otherPos = interactiveObject.GetOtherStairPosition();
                        Vector2 dir = otherPos - position;
                        dir.Normalize();
                        position += dir * 15;
                        if (position.Y < otherPos.Y) { Audio.PlayCue("vampire_stairs"); state.Change(States.UpStairs2); position = otherPos; }
                    }
                    break;
                case States.UpStairs2:
                    if (state.completed)
                    {
                        isStealth = false;
                        state.Change(States.Idle);
                        isAnimating = false;
                        position.Y += 30;
                    }
                    break;
                case States.DownStairs1:
                    if (state.completed)
                    {
                        Vector2 otherPos = interactiveObject.GetOtherStairPosition();
                        Vector2 dir = otherPos - position;
                        dir.Normalize();
                        position += dir * 15;
                        if (position.Y > otherPos.Y) { Audio.PlayCue("vampire_stairs"); state.Change(States.DownStairs2); position = otherPos; }
                    }
                    break;
                case States.DownStairs2:
                    if (state.completed)
                    {
                        isStealth = false;
                        state.Change(States.Idle);
                        isAnimating = false;
                        position.Y += 30;
                    }
                    break;
                case States.Die:
                    if (state.completed)
                    {
                        GameScreenManager.ChangeScreen(new LevelSelectScreen());
                        alive = true;
                        isStealth = false;
                        state.Change(States.Idle);
                    }
                    break;
            }
            return;
        }

        private void UpdateInput(GameTime gameTime)
        {
            if (!alive || isAnimating) return;

            if (!isStealth && Input.KeyDown(Keys.Left))
            {
                speed.X = -moveSpeed;
                isFacingLeft = true;
                if (onGround) state.Change(States.Walk);
            }
            else if (!isStealth && Input.KeyDown(Keys.Right))
            {
                speed.X = moveSpeed;
                isFacingLeft = false;
                if (onGround) state.Change(States.Walk);
            }
            else if (onGround)
                state.Change(States.Idle);

            if (!isStealth && onGround && Input.KeyPressed(Keys.Space))
            {
                Audio.PlayCue("vampire_jump");
                speed.Y = -jumpHeight;
                onGround = false;
                state.Change(States.Jump);
            }

            if (!onGround && speed.Y >= 0)
                state.Change(States.Fall);

            if (Input.KeyPressed(Keys.C) && interactiveObject != null && !interactiveObject.isOccupied)
            {
                isStealth = true;
                isAnimating = true;
                position = interactiveObject.position;
                speed = Vector2.Zero;
                isFacingLeft = false;
                switch (interactiveObject.type)
                {
                    case InteractiveObject.UpStairs: Audio.PlayCue("vampire_stairs"); state.Change(States.UpStairs1); break;
                    case InteractiveObject.DownStairs: Audio.PlayCue("vampire_stairs"); state.Change(States.DownStairs1); break;
                    case InteractiveObject.Door: Audio.PlayCue("door"); state.Change(States.DoorIn); break;
                }
                return;
            }
        }

        public override void Draw(SpriteBatch spriteBatch)
        {
            if (interactiveObject != null) spriteBatch.Draw(interactiveObjectIndicator, interactiveObject.drawPosition, Color.White);

            if ((state.actualState == States.UpStairs1 || state.actualState == States.DownStairs1) && state.completed) return;
            spriteBatch.Draw(sprite, drawPosition, sourceRectangle, Color.White, rotation, origin, scale, isFacingLeft ? SpriteEffects.FlipHorizontally : SpriteEffects.None, 0);

            //DrawCollidingTiles(spriteBatch);
            //DrawHitBox(spriteBatch);
        }

        public void Die()
        {
            isAnimating = true;
            isStealth = true;
            Audio.PlayCue("vampire_die");
            Audio.PlayCue("alarm");
            alive = false;
            state.Change(States.Die);
        }

        public static class States
        {
            public const int Idle = 0;
            public const int Walk = 1;
            public const int Jump = 2;
            public const int Fall = 3;
            public const int Die = 4;
            public const int UpStairs1 = 5;
            public const int UpStairs2 = 6;
            public const int DownStairs1 = 7;
            public const int DownStairs2 = 8;
            public const int DoorIn = 9;
            public const int DoorOut = 10;
        }
    }
}
